﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using ClassLibrary;

namespace XmlToCN
{
    public partial class Form1 : Form
    {
        Config Conf;
        public Form1()
        {
            InitializeComponent();

            AsNum.JsonConfig.JsonConfig.Regist<Config>();
            Conf = AsNum.JsonConfig.JsonConfig.Get<Config>();
            textBox来源.Text = Conf.SourceFile;
            textBox目标.Text = Conf.TargetFile;
            textBoxBaiduAppId.Text = Conf.BaiDuFYAppId;
            textBoxBaiduKey.Text = Conf.BaiDuFYKey;
            textBoxTags.Text = Conf.Tags;
            comboBoxType.SelectedIndex = Conf.XmlType;
        }

        private void buttonS_Click(object sender, EventArgs e)
        {
            openFileDialogS.Reset();
            if (System.IO.Path.IsPathRooted(textBox来源.Text))
            {
                openFileDialogS.InitialDirectory = System.IO.Path.GetDirectoryName(textBox来源.Text);
            }
            if (openFileDialogS.ShowDialog() == DialogResult.OK)
            {
                textBox来源.Text = openFileDialogS.FileName;
                buttonLoad.Enabled = true;

                buttonNoKey.Enabled = false;
                buttonPrev.Enabled = false;
                buttonNext.Enabled = false;
                buttonUpdate.Enabled = false;
                buttonSaveFile.Enabled = false;
                buttonFY.Enabled = false;
            }
        }

        private void buttonT_Click(object sender, EventArgs e)
        {
            openFileDialogT.Reset();
            if (System.IO.Path.IsPathRooted(textBox目标.Text))
            {
                openFileDialogT.InitialDirectory = System.IO.Path.GetDirectoryName(textBox目标.Text);
            }
            if (openFileDialogT.ShowDialog() == DialogResult.OK)
            {
                textBox目标.Text = openFileDialogT.FileName;
                buttonLoad.Enabled = true;

                buttonNoKey.Enabled = false;
                buttonPrev.Enabled = false;
                buttonNext.Enabled = false;
                buttonUpdate.Enabled = false;
                buttonSaveFile.Enabled = false;
                buttonFY.Enabled = false;
            }
        }

        XDocument xml来源;
        IEnumerable<XElement> xml来源List;
        XDocument xml目标;
        IEnumerable<XElement> xml目标List;

        string[] tags = new string[0];

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            if (comboBoxType.SelectedIndex < 0)
            {
                textBoxNote.Text = "请选择需要翻译的XML类型";
                return;
            }

            buttonUpdate_Click(sender, e);

            // 1 读取目标和来源XML
            if (!File.Exists(textBox来源.Text))
            {
                textBoxNote.Text = "来源无法读取或者不存在";
                return;
            }
            xml来源 = GetXmlDocument(textBox来源.Text);
            xml来源List = GetXmlList(xml来源);

            if (!File.Exists(textBox目标.Text))
            {
                textBoxNote.Text = "目标无法读取或者不存在";
                return;
            }
            xml目标 = GetXmlDocument(textBox目标.Text);
            xml目标List = GetXmlList(xml目标);

            if (!string.IsNullOrWhiteSpace(textBoxTags.Text))
            {
                tags = textBoxTags.Text.Split(',');
            }

            buttonLoad.Enabled = false;

            textBoxNote.Text = "读取完成";

            ConfSave();

            entryIndex = -1;

            buttonNext_Click(sender, e);

            buttonNoKey.Enabled = true;
            buttonPrev.Enabled = true;
            buttonNext.Enabled = true;
            buttonUpdate.Enabled = true;
            buttonSaveFile.Enabled = true;
            buttonFY.Enabled = true;

            progressBar1.Minimum = 0;
            progressBar1.Maximum = xml来源List.Count() - 1;
        }

        int entryIndex = -1;
        XElement sEntry;
        XElement tEntry;

        private void buttonNext_Click(object sender, EventArgs e)
        {
            if (entryIndex < xml来源List.Count())
            {
                entryIndex++;
            }

            if (xml来源List.Count() <= entryIndex || entryIndex < 0)
            {
                textBoxNote.Text = "最后一条了";
                return;
            }
            progressBar1.Value = entryIndex;
            KeyCompare();
        }

        private void buttonPrev_Click(object sender, EventArgs e)
        {
            if (entryIndex > 0)
            {
                entryIndex--;
            }

            if (xml来源List.Count() <= entryIndex || entryIndex < 0)
            {
                textBoxNote.Text = "第一条了";
                return;
            }
            progressBar1.Value = entryIndex;
            KeyCompare();
        }

        /// <summary>
        /// 根据来源对比目标条目,如果不存在的KEY则复制一份过去
        /// </summary>
        private void KeyCompare()
        {
            if (checkBoxAutoUp.Checked)
            {
                buttonUpdate_Click(null, null);
            }

            sEntry = null;
            tEntry = null;

            sEntry = xml来源List.ElementAt(entryIndex);

            textBox来源标题.Text = GetXmlKey(sEntry);
            textBox来源内容.Text = GetXmlVal(sEntry);

            var xmlTList = xml目标List.Where(entry => GetXmlKey(entry).Equals(textBox来源标题.Text));
            if (xmlTList.Count() == 0)
            {//复制来源条目到目标合集
                tEntry = CopyXmlKey();

                textBoxNote.Text = $"{sEntry.Name} 索引:{entryIndex} 目标中此条不存在,请汉化";
            }
            else
            {
                var xmlSList = xml来源List.Take(entryIndex).Where(entry => GetXmlKey(entry).Equals(textBox来源标题.Text));
                if (xmlSList.Count() > xmlTList.Count())
                {
                    tEntry = xmlTList.First();
                }
                else
                {
                    tEntry = xmlTList.ElementAt(xmlSList.Count());
                }
                textBoxNote.Text = $"{sEntry.Name} 索引:{entryIndex}";
            }

            textBox目标标题.Text = GetXmlKey(tEntry);
            textBox目标内容.Text = GetXmlVal(tEntry);
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            ConfSave();

            buttonUpdate_Click(sender, e);

            buttonSaveFile.Enabled = false;

            textBoxNote.Text = "保存中";

            if (checkBoxSaveS.Checked)
            {
                XDocument xmlNew = new XDocument(xml来源);
                var xmlNewList = GetXmlList(xmlNew);

                for (int i = 0; i < xmlNewList.Count(); i++)
                {//从来源中获取文本替换目标条目文本,最后覆盖到目标文本
                    var item = xmlNewList.ElementAt(i);
                    string key = GetXmlKey(item);

                    XElement t目标条目 = null;

                    var xmlTList = xml目标List.Where(entry => GetXmlKey(entry).Equals(key));

                    if (xmlTList.Count() == 0)
                    {
                        t目标条目 = xmlTList.FirstOrDefault();
                    }
                    else
                    {
                        var xmlSList = xmlNewList.Take(i).Where(entry => GetXmlKey(entry).Equals(key));
                        if (xmlSList.Count() > xmlTList.Count())
                        {
                            t目标条目 = xmlTList.First();
                        }
                        else
                        {
                            t目标条目 = xmlTList.ElementAt(xmlSList.Count());
                        }
                    }

                    if (t目标条目 != null && key == GetXmlKey(item))
                    {
                        SetXmlVal(item, GetXmlVal(t目标条目));
                    }

                }
                SaveXmlDocument(xmlNew);
            }
            else
            {
                SaveXmlDocument(xml目标);
            }


            textBoxNote.Text = "保存完毕";

            buttonSaveFile.Enabled = true;
            buttonLoad.Enabled = true;
        }

        private void ConfSave()
        {
            Conf.SourceFile = textBox来源.Text;
            Conf.TargetFile = textBox目标.Text;
            Conf.BaiDuFYAppId = textBoxBaiduAppId.Text;
            Conf.BaiDuFYKey = textBoxBaiduKey.Text;
            Conf.XmlType = comboBoxType.SelectedIndex;
            Conf.Tags = textBoxTags.Text;
            AsNum.JsonConfig.JsonConfig.Save(Conf);
        }

        private void buttonEnabled()
        {
            buttonS.Enabled = !buttonS.Enabled;
            buttonT.Enabled = !buttonT.Enabled;
            buttonNoKey.Enabled = !buttonNoKey.Enabled;
            buttonPrev.Enabled = !buttonPrev.Enabled;
            buttonNext.Enabled = !buttonNext.Enabled;
            buttonUpdate.Enabled = !buttonUpdate.Enabled;
            buttonSaveFile.Enabled = !buttonSaveFile.Enabled;
            buttonFY.Enabled = !buttonFY.Enabled;
        }

        private void buttonNoKey_Click(object sender, EventArgs e)
        {
            buttonEnabled();
            entryIndex++;
            textBoxNote.Text = "开始查找...";
            Form1.CheckForIllegalCrossThreadCalls = false;
            //ThreadStart ts = new ThreadStart(FindKey);
            //Thread th = new Thread(ts);
            //th.Start();
            FindKey();
        }

        private void FindKey()
        {
            bool noKey = false;
            for (int i = entryIndex; i < xml来源List.Count(); i++)
            {
                var item = xml来源List.ElementAt(i);
                string key = GetXmlKey(item);

                progressBar1.Value = i;

                textBoxNote.Text = $"匹配 {key} 中";

                if (!string.IsNullOrWhiteSpace(key))
                {
                    var itemSVal = GetXmlVal(item);
                    if (string.IsNullOrWhiteSpace(itemSVal))
                    {
                        continue;
                    }

                    //根据key查找目标集合中是否有该key
                    var tempTList = xml目标List.Where(entry => GetXmlKey(entry).Equals(key));


                    if (tempTList.Count() == 0)
                    {
                        noKey = true;
                        entryIndex = i;
                        break;
                    }
                    else
                    {
                        var elementT = tempTList.First();

                        var itemTVal = GetXmlVal(elementT);
                        var item源有中文 = Regex.IsMatch(itemSVal, @"[\u4e00-\u9fa5]");
                        var item目标有中文 = Regex.IsMatch(itemTVal, @"[\u4e00-\u9fa5]");

                        if ((item源有中文 && !itemSVal.Equals(itemTVal)) || (!item源有中文 && itemSVal.Equals(itemTVal)) || (!item源有中文 && !item目标有中文 && !itemSVal.Equals(itemTVal)))
                        {//源和目标都包含中文,并且文本不相同. 源没有中文,文本相同的. 源和目标都不包含中文,并且文本不相同的
                            noKey = true;
                            entryIndex = i;
                            break;
                        }
                        else if (!item源有中文 && item目标有中文)
                        {
                            bool notag = false;
                            foreach (var tag in tags)
                            {
                                if (itemSVal.Contains(tag) && !itemTVal.Contains(tag))
                                {//来源存在的标签,但是目标中却不存在.
                                    noKey = true;
                                    entryIndex = i;
                                    notag = true;
                                    break;
                                }
                            }
                            if (notag) break;

                        }
                    }
                }
            }

            if (noKey)
            {
                KeyCompare();
            }
            else
            {
                textBoxNote.Text = "找不到";
            }
            buttonEnabled();
        }

        private void buttonUpdate_Click(object sender, EventArgs e)
        {
            if (tEntry != null && !string.IsNullOrWhiteSpace(textBox目标内容.Text) && !GetXmlVal(tEntry).Equals(textBox目标内容.Text))
            {
                SetXmlVal(tEntry, textBox目标内容.Text);
            }
        }

        private void buttonFY_Click(object sender, EventArgs e)
        {
            ClassLibrary.BaiduFanyi.TranslationResult result = ClassLibrary.BaiduFanyi.Fanyi.GetTranslationFromBaiduFanyi(textBox来源内容.Text, ClassLibrary.BaiduFanyi.Language.en, ClassLibrary.BaiduFanyi.Language.zh, textBoxBaiduAppId.Text, textBoxBaiduKey.Text);
            //判断是否出错
            if (result.Error_code == null)
            {
                string[] newText = new string[result.Trans_result.Count()];
                for (int i = 0; i < newText.Count(); i++)
                {
                    newText[i] = result.Trans_result[i].Dst;
                }
                textBox目标内容.Lines = newText;
                textBoxNote.Text = $"{sEntry.Name} 索引:{entryIndex} 机翻成功";
            }
            else
            {
                //检查appid和密钥是否正确
                textBoxNote.Text = "翻译出错，错误码：" + result.Error_code + "，错误信息：" + result.Error_msg;
            }
        }

        public XDocument GetXmlDocument(string path)
        {
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    return XDocument.Load(path, LoadOptions.PreserveWhitespace);
                case 1:
                    var sr = File.OpenText(path);
                    string sxml = sr.ReadToEnd().Replace("&", "{[").Replace(";", "]}");
                    sr.Close();
                    return XDocument.Parse(sxml, LoadOptions.PreserveWhitespace);
                default:
                    return null;
            }
        }

        public IEnumerable<XElement> GetXmlList(XDocument xd)
        {
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    return xd.Descendants("Entry");
                case 1:
                    return xd.Elements().Descendants();
                default:
                    return null;
            }
        }

        public string GetXmlKey(XElement xe)
        {
            string key = null;

            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    key = xe?.Attribute("Key")?.Value?.ToString();
                    break;
                case 1:
                    key = xe?.Name.ToString();
                    break;
                default:
                    break;
            }

            return key;
        }

        public string GetXmlVal(XElement xe)
        {
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    return xe?.Attribute("Val")?.Value?.ToString();
                case 1:
                    return xe?.Value;
                default:
                    return null;
            }
        }

        public XElement CopyXmlKey()
        {
            XElement xml条目父级;
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    xml条目父级 = xml目标.Descendants().First().Descendants().First();
                    xml条目父级.Add(@"
  ");//添加换行
                    xml条目父级.Add(sEntry);
                    return xml条目父级.Descendants().First();
                case 1:
                    xml条目父级 = xml目标.Elements().First();
                    xml条目父级.Add(@"
  ");//添加换行
                    xml条目父级.Add(sEntry);
                    return xml条目父级.Descendants().Last();
                default:
                    return null;
            }
        }

        public void SetXmlVal(XElement xe, string val)
        {
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    xe.Attribute("Val").Value = val;
                    break;
                case 1:
                    xe.Value = val;
                    break;
                default:
                    break;
            }
        }

        public void SaveXmlDocument(XDocument xd)
        {
            switch (comboBoxType.SelectedIndex)
            {
                case 0:
                    XmlWriterSettings xws = new XmlWriterSettings();
                    xws.OmitXmlDeclaration = true;
                    using (XmlWriter xw = XmlWriter.Create(textBox目标.Text, xws))
                    {
                        xd.Save(xw);
                    }
                    break;
                case 1:
                    var elm = xd.Elements().First();
                    elm.Attribute("language").Value = "Simplified Chinese";
                    elm.Attribute("nowhitespace").Value = "true";
                    elm.Attribute("translatedname").Value = "中文(简体)";
                    xd.Declaration = new XDeclaration("1.0", "utf-8", "yes");
                    File.WriteAllText(textBox目标.Text, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + xd.ToString().Replace("{[", "&").Replace("]}", ";"));
                    break;
                default:
                    break;
            }
        }

    }
}
